﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.DataAccess.SqlServer.Model;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.DataAccess.Implementaciones.SQL
{
    /// <summary>
    /// Clase de las operaciones de Acceso a Datos para el módulo Actualizacion de Versión Válida.
    /// </summary>
    public class ActualizaVersionDao : IActualizaVersionDao
    {
        /// <summary>
        /// Obtiene todos los archivos activos versionables que coincidan con los filtros.
        /// </summary>
        /// <param name="actualizacionVersionFilters">Contienen los filtros que serán aplicados en la búsqueda.</param>
        /// <returns>Lista de archivos versionables</returns>
        public IList<ActualizacionVersionInfo> GetArchivosVersionables(ActualizacionVersionInfo actualizacionVersionFilters)
        {
            IList<ActualizacionVersionInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = from cargaArchivo in context.MIAP_CARGA_ARCHIVO
                            join archivo in context.MIAP_ARCHIVO
                            on cargaArchivo.ID_ARCHIVO equals archivo.ID_ARCHIVO     
                            join bitacoraGeneralCargaArchivo in context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                            on cargaArchivo.ID_CARGA_ARCHIVO equals bitacoraGeneralCargaArchivo.ID_CARGA_ARCHIVO
                            join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                            on bitacoraGeneralCargaArchivo.ID_BITACORA_GENERAL equals bitacoraGeneral.ID_BITACORA_GENERAL
                            join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                            on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraArchivo.ID_BITACORA_GENERAL
                            join proyecto in context.MIAP_PROYECTO
                            on archivo.ID_PROYECTO equals proyecto.ID_PROYECTO   
                            where (archivo.VERSION == true && archivo.ACTIVO == true
                            && (!actualizacionVersionFilters.IdProyecto.HasValue || archivo.ID_PROYECTO == actualizacionVersionFilters.IdProyecto)
                            && (!actualizacionVersionFilters.IdArchivo.HasValue || archivo.ID_ARCHIVO == actualizacionVersionFilters.IdArchivo)
                            && (!actualizacionVersionFilters.Mes.HasValue || cargaArchivo.MES == actualizacionVersionFilters.Mes)
                            && (!actualizacionVersionFilters.Año.HasValue || cargaArchivo.AÑO == actualizacionVersionFilters.Año)
                            && (bitacoraGeneral.ID_ESTATUS_PROCESO == (int)EstatusProceso.Finalizado_Correcto))
                            select new ActualizacionVersionInfo
                            {                                                
                                IdCargaArchivo = cargaArchivo.ID_CARGA_ARCHIVO, 
                                IdArchivo = archivo.ID_ARCHIVO,
                                IdProyecto = archivo.ID_PROYECTO,                                
                                NombreProyecto = proyecto.NOMBRE,
                                NombreArchivo = archivo.NOMBRE, 
                                TipoProceso = bitacoraGeneral.MIAP_TIPO_PROCESO.NOMBRE,
                                FechaProceso = bitacoraArchivo.FECHA_ACTUALIZACION,
                                Año = cargaArchivo.AÑO,
                                Mes = cargaArchivo.MES,                                
                                Version = cargaArchivo.VERSION == null ? string.Empty : cargaArchivo.VERSION,
                                Versionable = archivo.VERSION,
                                VersionValida = cargaArchivo.VERSION_VALIDA == true ? "Si" : ""
                            };

                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Obtiene el autorizador de la recarga del archivo.
        /// </summary>
        /// <param name="listArchivos">Lista de los ids de carga de los archivos y sus versiones.</param>
        /// <returns>Lista con los nombres de los autorizadores.</returns>
        public IList<EjecutorInfo> GetAutorizador(List<CatalogoInfo> listArchivos)
        {
            List<EjecutorInfo> listAutorizadores = new List<EjecutorInfo>(); ;

            using (var context = new MIAPDBEntities())
            {
                foreach (CatalogoInfo archivo in listArchivos)
                {
                    var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                                join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                                on usuario.ID_USUARIO equals bitacoraGeneral.ID_USUARIO              
                                join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                                on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraArchivo.ID_BITACORA_GENERAL
                                join bitacoraGeneralCargaArchivo in context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                                on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraGeneralCargaArchivo.ID_BITACORA_GENERAL                            
                                where (bitacoraGeneralCargaArchivo.ID_CARGA_ARCHIVO == archivo.IdItem
                                && bitacoraArchivo.VERSION == archivo.Descripcion    
                                && (bitacoraGeneral.ID_TIPO_PROCESO == (int)TipoProceso.Recarga))                                
                                select new EjecutorInfo
                                {
                                    IdCargaArchivo = archivo.IdItem,
                                    NombreEjecutor = usuario.Nombre + " " + usuario.ApellidoPaterno + " " + usuario.ApellidoMaterno,
                                    VersionArchivo = bitacoraArchivo.VERSION                                    
                                };
                    
                    EjecutorInfo autorizador = query.OrderByDescending(p => p.FechaProceso).FirstOrDefault();

                    if (autorizador != null)
                    {
                        listAutorizadores.Add(autorizador);
                    }
                }
            }

            return listAutorizadores;
        }

        /// <summary>
        /// Obtiene el nombre del versionador de la carga o recarga del archivo.
        /// </summary>
        /// <param name="listArchivos">Lista de archivos versionables.</param>
        /// <returns>Lista de ids de archivos y sus respectivos versionadores.</returns>
        public IList<CatalogoInfo> GetNombreVersionador(List<CatalogoInfo> listArchivos)
        {
            IList<CatalogoInfo> result = new List<CatalogoInfo>();

            CatalogoInfo versionador = new CatalogoInfo();

            using (var context = new MIAPDBEntities())
            {
                foreach (CatalogoInfo archivo in listArchivos)
                {
                    var query = (from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                                join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                                on usuario.ID_USUARIO equals bitacoraGeneral.ID_USUARIO                                
                                join bitacoraGeneralCargaArchivo in context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                                on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraGeneralCargaArchivo.ID_BITACORA_GENERAL
                                join cargaArchivo in context.MIAP_CARGA_ARCHIVO
                                on bitacoraGeneralCargaArchivo.ID_CARGA_ARCHIVO equals cargaArchivo.ID_CARGA_ARCHIVO
                                join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                                on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraArchivo.ID_BITACORA_GENERAL
                                where (bitacoraGeneralCargaArchivo.ID_CARGA_ARCHIVO == archivo.IdItem 
                                && bitacoraArchivo.VERSION == archivo.Descripcion )
                                select new CatalogoInfo()
                                {
                                    IdItem = cargaArchivo.ID_CARGA_ARCHIVO,
                                    Descripcion = string.Format("{0}{1}{2}{3}{4}", usuario.Nombre, " ", usuario.ApellidoPaterno, " ", usuario.ApellidoMaterno)
                                }).Distinct();

                    versionador = query.First();

                    result.Add(versionador);
                }
            }

            return result;
        }

        /// <summary>
        /// Modifica la versión válida de un archivo.
        /// </summary>
        /// <param name="actualizacionVersion">Archivo que será modificado.</param>
        /// <param name="user">Usuario que ehecuta la operación.</param>
        public void EditVersionValida(ActualizacionVersionInfo actualizacionVersion, string user)
        {
            using(var context = new MIAPDBEntities())
            {
                 MIAP_BITACORA_GENERAL miapBitacoraGeneral = new MIAP_BITACORA_GENERAL()
                {
                    ID_USUARIO = actualizacionVersion.IdUsuario.Value,
                    ID_TIPO_PROCESO = (int)TipoProceso.ActualizacionVersionValida,
                    ID_ESTATUS_PROCESO = (int)EstatusProceso.Inicio,
                    AÑO = actualizacionVersion.Año.Value,
                    MES = actualizacionVersion.Mes.Value,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_GENERAL.Add(miapBitacoraGeneral);

                MIAP_BITACORA_ARCHIVO miapBitacoraArchivo = new MIAP_BITACORA_ARCHIVO()
                {
                    ID_BITACORA_GENERAL = miapBitacoraGeneral.ID_BITACORA_GENERAL,
                    ID_ARCHIVO = actualizacionVersion.IdArchivo.Value,
                    NOMBRE_ARCHIVO = actualizacionVersion.NombreArchivo,   
                    VERSION = actualizacionVersion.Version,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_ARCHIVO.Add(miapBitacoraArchivo);

                MIAP_CARGA_ARCHIVO miapCargaArchivoVersionAnterior = new MIAP_CARGA_ARCHIVO();
                MIAP_CARGA_ARCHIVO miapCargaArchivo = new MIAP_CARGA_ARCHIVO();

                miapCargaArchivoVersionAnterior = (from cargaArchivo in context.MIAP_CARGA_ARCHIVO
                                                   where (cargaArchivo.ID_ARCHIVO == actualizacionVersion.IdArchivo                                                   
                                                   && cargaArchivo.VERSION_VALIDA == true)
                                                   select cargaArchivo).SingleOrDefault();

                if (miapCargaArchivoVersionAnterior != null)
                {
                    miapCargaArchivoVersionAnterior.VERSION_VALIDA = false;
                    miapCargaArchivoVersionAnterior.USUARIO_MODIFICACION = user;
                    miapCargaArchivoVersionAnterior.FECHA_MODIFICACION = DateTime.Now;
                }

                miapCargaArchivo = (from cargaArchivo in context.MIAP_CARGA_ARCHIVO
                                    where cargaArchivo.ID_CARGA_ARCHIVO == actualizacionVersion.IdCargaArchivo
                                    select cargaArchivo).Single();

                miapCargaArchivo.VERSION_VALIDA = true;
                miapCargaArchivo.USUARIO_MODIFICACION = user;
                miapCargaArchivo.FECHA_MODIFICACION = DateTime.Now;

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Obtiene el nombre de la versión válida del archivo.
        /// </summary>
        /// <param name="idArchivo">Es el id del archivo del cual se dese obtener la versión válida.</param>
        /// <returns>Nombre de la versión válida del archivo.</returns>
        public string GetNombreVersionValidaArchivo(int idArchivo)
        {
            string result;

            using (var context = new MIAPDBEntities())
            {
                var query = from cargaArchivo in context.MIAP_CARGA_ARCHIVO
                            join archivo in context.MIAP_ARCHIVO
                            on cargaArchivo.ID_ARCHIVO equals archivo.ID_ARCHIVO
                            where (archivo.VERSION == true && archivo.ACTIVO == true
                            && archivo.ID_ARCHIVO == idArchivo
                            && cargaArchivo.VERSION_VALIDA == true)
                            select cargaArchivo.VERSION;

                result = query.SingleOrDefault();
            }

            return result;
        }
    }
}
